package com.example.emos.api.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.example.emos.api.common.util.PageUtils;
import com.example.emos.api.common.util.R;
import com.example.emos.api.controller.form.*;
import com.example.emos.api.db.pojo.TbUser;
import com.example.emos.api.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/user")
@Tag(name = "UserController", description = "用户Web接口")
public class UserController {
    @Autowired
    private UserService userService;


    @PostMapping("/delete")
    @SaCheckPermission(value = {"ROOT", "USER:DELETE"}, mode = SaMode.OR)
    @Operation(summary = "删除用户")
    public R deleteUserByIds(@Valid @RequestBody DeleteUserForm form) {
        //TODO 不能删除自己
        if (ArrayUtil.contains(form.getIds(), StpUtil.getLoginIdAsInt())){
            return R.error("不能删除自己的账户");
        }
        int rows = this.userService.deleteUserByIds(form.getIds());
        //TODO 被删除的用户，会被踢下线
        if (rows >= 1) {
            Arrays.stream(form.getIds()).peek(StpUtil::logoutByLoginId);
        }
        return R.ok().put("rows", rows);
    }


    @PostMapping("/update")
    @SaCheckPermission(value = {"ROOT", "USER:UPDATE"}, mode = SaMode.OR)
    @Operation(summary = "修改用户")
    public R updateUser(@Valid @RequestBody UpdateUserForm form) {
        TbUser tbUser = JSONUtil.parse(form).toBean(TbUser.class);
        tbUser.setRole(JSONUtil.parseArray(form.getRole()).toString());
        int rows = this.userService.update(tbUser);
        //TODO 修改成功后，把用户踢下线
        if (1 == rows) {
            StpUtil.logoutByLoginId(form.getId());
        }
        return R.ok().put("rows", rows);
    }

    @PostMapping("/insert")
    @SaCheckPermission(value = {"ROOT", "USER:INSERT"}, mode = SaMode.OR)
    @Operation(summary = "新增用户")
    public R insertUser(@Valid @RequestBody InsertUserForm form) {
        //TODO 前段传过来的数据校验后,转成PO对象
        TbUser tbUser = JSONUtil.parse(form).toBean(TbUser.class);
        tbUser.setStatus((byte) 1);
        //TODO 数据库中对应的字段role是JSON类型,需要解析成JSON数组对象保存到数据库中
        tbUser.setRole(JSONUtil.parseArray(form.getRole()).toString());
        tbUser.setCreateTime(new Date());
        int rows = this.userService.insert(tbUser);
        return R.ok().put("rows", rows);

    }

    @GetMapping("/logout")
    @Operation(description = "退出系统")
    public R logout() {
        StpUtil.logout();
        return R.ok();
    }

    @PostMapping("/userList")
    @SaCheckLogin
    @SaCheckPermission(value = {"ROOT", "USER:SELECT"}, mode = SaMode.OR)
    @Operation(summary = "查询用户")
    public R listUser(@Valid @RequestBody SearchUserByPageForm form) {
        int page = form.getPage();
        int length = form.getLength();
        int start = (page - 1) * length;
        HashMap parameter = JSONUtil.parse(form).toBean(HashMap.class);
        parameter.put("start", start);
        PageUtils pageUtils = this.userService.searchUserByPage(parameter);
        return R.ok().put("page", pageUtils);
    }

    @PostMapping("/updatePassword")
    @SaCheckLogin
    @Operation(summary = "修改密码")
    public R updatePassword(@Valid @RequestBody UpdatePassword updatePassword) {
        int loginIdAsInt = StpUtil.getLoginIdAsInt();
        HashMap hashMap = new HashMap<>() {{
            put("userId", loginIdAsInt);
            put("password", updatePassword.getPassword());
        }};
        int row = this.userService.updatePassword(hashMap);

        return R.ok().put("row", row);
    }


    @PostMapping("/login")
    @Operation(summary = "登录")
    public R login(@Valid @RequestBody LoginFrom loginFrom) {
        HashMap hashMap = JSONUtil.parse(loginFrom).toBean(HashMap.class);
        Integer userId = this.userService.login(hashMap);
        R r = R.ok().put("result", userId != null);
        if (userId != null) {
            Set<String> permissions = this.userService.searchUserPermissions(userId);

            StpUtil.setLoginId(userId); //Sa-Token 权限验证工具类
            String token = StpUtil.getTokenInfo().getTokenValue();

            r.put("permissions", permissions).put("token", token);
        }

        return r;

    }

    /**
     * 生成登陆二维码的字符串
     */
    @GetMapping("/createQrCode")
    @Operation(summary = "生成二维码Base64格式的字符串")
    public R createQrCode() {
        HashMap map = userService.createQrCode();
        return R.ok(map);
    }

    /**
     * 检测登陆验证码
     *
     * @param form
     * @return
     */
    @PostMapping("/checkQrCode")
    @Operation(summary = "检测登陆验证码")
    public R checkQrCode(@Valid @RequestBody CheckQrCodeForm form) {
        boolean bool = userService.checkQrCode(form.getCode(), form.getUuid());
        return R.ok().put("result", bool);
    }

    @PostMapping("/wechatLogin")
    @Operation(summary = "微信小程序登陆")
    public R wechatLogin(@Valid @RequestBody WechatLoginForm form) {
        HashMap map = userService.wechatLogin(form.getUuid());
        boolean result = (boolean) map.get("result");
        if (result) {
            int userId = (int) map.get("userId");
            StpUtil.setLoginId(userId);
            Set<String> permissions = userService.searchUserPermissions(userId);
            map.remove("userId");
            map.put("permissions", permissions);
        }
        return R.ok(map);
    }

    /**
     * 登陆成功后加载用户的基本信息
     */
    @GetMapping("/loadUserInfo")
    @Operation(summary = "登陆成功后加载用户的基本信息")
    @SaCheckLogin
    public R loadUserInfo() {
        int userId = StpUtil.getLoginIdAsInt();
        HashMap summary = userService.searchUserSummary(userId);
        return R.ok(summary);
    }

    @PostMapping("/searchById")
    @Operation(summary = "根据ID查找用户")
    @SaCheckPermission(value = {"ROOT", "USER:SELECT"}, mode = SaMode.OR)
    public R searchById(@Valid @RequestBody SearchUserByIdForm form) {
        HashMap map = userService.searchById(form.getUserId());
        return R.ok(map);
    }

    @GetMapping("/searchAllUser")
    @Operation(summary = "查询所有用户")
    @SaCheckLogin
    public R searchAllUser() {
        ArrayList<HashMap> list = userService.searchAllUser();
        return R.ok().put("list", list);
    }
}
